from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from apps.classmembers.models import StudentClass
from apps.classes.models import Class
from apps.students.models import Student
from rest_framework import status
from apps.classes.serializers import ClassModelSerializer
from apps.students.serializers import StudentModelSerializer
from json.decoder import JSONDecodeError
from apps.students.pagination import StudentPageNumberPagination
import json


# Create your views here.
class ClassesMembersViewSet(ViewSet):

    @staticmethod
    def delete_class_member(request, cid, sid):
        cls_stu = StudentClass.objects.filter(classes_id=cid, student_id=sid).first()
        if not cls_stu:
            return Response({"message": "未查询到该班级成员!"}, status=status.HTTP_400_BAD_REQUEST)

        cls_stu.delete()
        return Response({"message": f"成功删除班级成员 【{cls_stu}】"}, status=status.HTTP_204_NO_CONTENT)

    @staticmethod
    def get_class_members(request):
        query_params = request.query_params
        cls_id = query_params.get('id')
        course_id = query_params.get('cid')
        stage_no = query_params.get('stage_no')
        # 参数校验
        if cls_id is None and not all([course_id, stage_no]):
            return Response({"message": " 【班级id】 和 【班期】 为必要参数！"}, status=status.HTTP_400_BAD_REQUEST)

        # 通过 "班级id" 查询班级是否存在
        if cls_id:
            try:
                cls = Class.objects.get(id=cls_id)
            except Class.DoesNotExist:
                return Response({"message": "班级不存在!"}, status=status.HTTP_400_BAD_REQUEST)
        # 通过 "班期" 和 "课程id" 查询班级是否存在
        else:
            try:
                cls = Class.objects.get(stage_no=stage_no, course_id=course_id)
            except Class.DoesNotExist:
                return Response({"message": "班级不存在!"}, status=status.HTTP_400_BAD_REQUEST)

        # 获取该班级在 学员班级表中的数据记录
        student_classes = cls.all_students.all()
        if not student_classes:
            return Response({"message": "该班级暂未录入学员!", "data": {'cls_id': cls.id}}, status=status.HTTP_200_OK)

        students = reversed([student_classe.student for student_classe in student_classes])

        # 使用PageNumberPagination类的实例来手动分页生成模型对象列表
        # 创建分页类实例(可修改分页类每页显示的对象数量)
        paginator = StudentPageNumberPagination()
        # paginator.page_size = 2
        # 获取分页之后的查询集,并获取序列化器对象
        paginated_queryset = paginator.paginate_queryset(list(students), request)
        serializer = StudentModelSerializer(paginated_queryset, many=True)
        # 获取分页之后的响应数据
        paginated_response = paginator.get_paginated_response(serializer.data)
        # 添加班级id
        paginated_response.data.update({'cls_id': cls.id})
        return Response({"message": f"成功获取【{str(cls)}】 班级的学员列表!", "data": paginated_response.data},
                        status=status.HTTP_200_OK)

    @staticmethod
    def get_class_members_latest(request):
        """获取最新的班级成员"""
        cls = Class.objects.last()
        # 获取该班级在 学员班级表中的数据记录
        student_classes = cls.all_students.all()
        if not student_classes:
            return Response({"message": "该班级暂未录入学员!", "data": []}, status=status.HTTP_200_OK)

        students = reversed([student_classe.student for student_classe in student_classes])

        # 使用PageNumberPagination类的实例来手动分页生成模型对象列表
        # 创建分页类实例(可修改分页类每页显示的对象数量)
        paginator = StudentPageNumberPagination()
        # paginator.page_size = 2
        # 获取分页之后的查询集,并获取序列化器对象
        paginated_queryset = paginator.paginate_queryset(list(students), request)
        serializer = StudentModelSerializer(paginated_queryset, many=True)
        # 获取分页之后的响应数据
        paginated_response = paginator.get_paginated_response(serializer.data)
        # 添加班级id
        paginated_response.data.update({'cls_id': cls.id})
        return Response({"message": f"成功获取最新班级【{str(cls)}】 的学员列表!", "data": paginated_response.data},
                        status=status.HTTP_200_OK)

    @staticmethod
    def add_class_members(request, cid):
        student_ids = request.data.get('members')
        # 参数校验
        if student_ids is None:
            return Response({"message": "缺少必要参数members"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            student_ids = json.loads(student_ids)
        except JSONDecodeError:
            return Response({"message": "参数格式错误,请按如下格式提交 [1,2,3] "}, status=status.HTTP_400_BAD_REQUEST)
        except TypeError:
            return Response({"message": "参数类型错误,请按如下格式提交 [1,2,3] "}, status=status.HTTP_400_BAD_REQUEST)
        else:
            if not isinstance(student_ids, list):
                return Response({"message": "参数类型错误,请按如下格式提交 [1,2,3] "}, status=status.HTTP_400_BAD_REQUEST)

        # 班级id合法性校验
        try:
            cls = Class.objects.get(id=cid)
        except Class.DoesNotExist:
            return Response({"message": "班级不存在!"}, status=status.HTTP_400_BAD_REQUEST)

        # 学员id合法性校验
        students = []
        for student_id in student_ids:
            try:
                student = Student.objects.get(id=student_id)
            except Student.DoesNotExist:
                return Response({"message": f"未查询到ID为{student_id}的学员!"}, status=status.HTTP_400_BAD_REQUEST)
            else:
                students.append(student)

        # 生成StudentClass的对象数据列表
        student_classes = [StudentClass(student=student, classes=cls) for student in students]
        # 检查这些对象是否在已经在StudentClass数据表中(注意student_classes对象是新创建的没有id)
        exists_in_db = StudentClass.objects.filter(
            classes_id=cid,
            student_id__in=[student_classe.student_id for student_classe in student_classes]
        ).exists()
        if exists_in_db:
            return Response({"message": "不能重复添加学员到班级!"}, status=status.HTTP_400_BAD_REQUEST)

        # 批量写入数据到数据库
        StudentClass.objects.bulk_create(student_classes)

        # 返回当前班级所有学员(按记录倒序返回)
        # 获取该班级在 学员班级表中的数据记录
        student_classes = cls.all_students.all()
        if not student_classes:
            return Response({"message": "该班级暂未录入学员!", "data": []}, status=status.HTTP_200_OK)

        students = reversed([student_classe.student for student_classe in student_classes])
        serializer = StudentModelSerializer(students, many=True)
        return Response({"message": f"成功添加学员到班级({str(cls)})列表!", "data": serializer.data},
                        status=status.HTTP_201_CREATED)

    @staticmethod
    def get_member_classes(request):
        query_params = request.query_params
        stu_id = query_params.get('id')
        sno = query_params.get('sno')
        IDCard = query_params.get('IDCard')
        # 参数校验 - 参数缺失
        if not any([stu_id, sno, IDCard]):
            return Response({"message": "请输入查询参数!"}, status=status.HTTP_400_BAD_REQUEST)

        # 参数校验 - 只允许接收一个查询参数
        if sum([bool(stu_id), bool(sno), bool(IDCard)]) != 1:
            return Response({"message": "只允许传递一个查询参数!"}, status=status.HTTP_400_BAD_REQUEST)

        # 根据学号查询学员
        if sno:
            try:
                stu = Student.objects.get(sno=sno)
            except Class.DoesNotExist:
                return Response({"message": f"未查询到学号为{sno}的学员!"}, status=status.HTTP_400_BAD_REQUEST)
        # 根据身份证号查询学员
        elif IDCard:
            try:
                stu = Student.objects.get(IDCard=IDCard)
            except Class.DoesNotExist:
                return Response({"message": f"未查询到身份证号为{IDCard}的学员!"}, status=status.HTTP_400_BAD_REQUEST)
        # 根据学员id查询学员
        else:
            try:
                stu = Student.objects.get(id=stu_id)
            except Student.DoesNotExist:
                return Response({"message": f"未查询到ID为{stu_id}的学员!"}, status=status.HTTP_400_BAD_REQUEST)

        # 获取该学员在 学员班级表中的数据记录
        student_classes = stu.all_classes.all()
        if not student_classes:
            return Response({"message": "该学员暂未进入任何班级!", "data": []}, status=status.HTTP_200_OK)

        classes = reversed([student_classe.classes for student_classe in student_classes])

        # 使用PageNumberPagination类的实例来手动分页生成模型对象列表
        # 创建分页类实例(可修改分页类每页显示的对象数量)
        paginator = StudentPageNumberPagination()
        # paginator.page_size = 2
        # 获取分页之后的查询集,并获取序列化器对象
        paginated_queryset = paginator.paginate_queryset(list(classes), request)
        serializer = ClassModelSerializer(paginated_queryset, many=True)
        # 获取分页之后的响应数据
        paginated_response = paginator.get_paginated_response(serializer.data)
        return Response({"message": f"成功获取学员 【{str(stu)}】 所在班级列表!", "data": paginated_response.data},
                        status=status.HTTP_200_OK)
